<script setup lang="ts">
import { onMounted, ref, reactive } from "vue"
const { Graph, Shape, Addon } = X6
import Right from "./right.vue"

const activeKey = ref("2")

// 初始化画布数据
let graph = reactive<any>({})

onMounted(() => {
    preWork()

    // #region 初始化画布
    graph = new Graph({
        container: document.getElementById("graph-container")!,
        grid: true,
        mousewheel: {
            enabled: true,
            zoomAtMousePosition: true,
            modifiers: "ctrl",
            minScale: 0.5,
            maxScale: 3,
        },
        connecting: {
            router: {
                name: "manhattan",
                args: {
                    padding: 1,
                },
            },
            connector: {
                name: "rounded",
                args: {
                    radius: 8,
                },
            },
            anchor: "center",
            connectionPoint: "anchor",
            allowBlank: false,
            snap: {
                radius: 20,
            },
            createEdge() {
                return new Shape.Edge({
                    attrs: {
                        line: {
                            // stroke: "#A2B1C3",
                            stroke: "#fff",
                            strokeWidth: 2,
                            targetMarker: {
                                name: "block",
                                width: 12,
                                height: 8,
                            },
                        },
                    },
                    zIndex: 14,
                })
            },
            validateConnection({ targetMagnet }) {
                return !!targetMagnet
            },
        },
        highlighting: {
            magnetAdsorbed: {
                name: "stroke",
                args: {
                    attrs: {
                        fill: "#5F95FF",
                        stroke: "#5F95FF",
                    },
                },
            },
        },
        resizing: true,
        rotating: true,
        selecting: {
            enabled: true,
            rubberband: true,
            showNodeSelectionBox: true,
        },
        snapline: true,
        keyboard: true,
        clipboard: true,
    })
    // #endregion

    // #region 初始化 stencil
    const stencil = new Addon.Stencil({
        title: "流程图",
        target: graph,
        stencilGraphWidth: 200,
        stencilGraphHeight: 180,
        collapsable: true,
        groups: [
            {
                title: "基础设施",
                name: "group1",
                graphHeight: 90,
                layoutOptions: {
                    rowHeight: 70,
                },
            },
            {
                title: "中间件",
                name: "group2",
                graphHeight: 90,
                layoutOptions: {
                    rowHeight: 70,
                },
            },
            {
                title: "业务系统",
                name: "group3",
                graphHeight: 90,
                layoutOptions: {
                    rowHeight: 70,
                },
            },
            {
                title: "服务",
                name: "group4",
                graphHeight: 90,
                layoutOptions: {
                    rowHeight: 70,
                },
            },
        ],
        layoutOptions: {
            columns: 2,
            columnWidth: 80,
            rowHeight: 55,
        },
    })
    document.getElementById("stencil")!.appendChild(stencil.container)
    // #endregion

    // #region 快捷键与事件
    // copy cut paste
    graph.bindKey(["meta+c", "ctrl+c"], () => {
        const cells = graph.getSelectedCells()
        if (cells.length) {
            graph.copy(cells)
        }
        return false
    })
    graph.bindKey(["meta+x", "ctrl+x"], () => {
        const cells = graph.getSelectedCells()
        if (cells.length) {
            graph.cut(cells)
        }
        return false
    })
    graph.bindKey(["meta+v", "ctrl+v"], () => {
        if (!graph.isClipboardEmpty()) {
            const cells = graph.paste({ offset: 32 })
            graph.cleanSelection()
            graph.select(cells)
        }
        return false
    })

    //undo redo
    graph.bindKey(["meta+z", "ctrl+z"], () => {
        if (graph.history.canUndo()) {
            graph.history.undo()
        }
        return false
    })
    graph.bindKey(["meta+shift+z", "ctrl+shift+z"], () => {
        if (graph.history.canRedo()) {
            graph.history.redo()
        }
        return false
    })

    // select all
    graph.bindKey(["meta+a", "ctrl+a"], () => {
        const nodes = graph.getNodes()
        if (nodes) {
            graph.select(nodes)
        }
    })

    //delete
    graph.bindKey("backspace", () => {
        const cells = graph.getSelectedCells()
        if (cells.length) {
            graph.removeCells(cells)
        }
    })

    // zoom
    graph.bindKey(["ctrl+1", "meta+1"], () => {
        const zoom = graph.zoom()
        if (zoom < 1.5) {
            graph.zoom(0.1)
        }
    })
    graph.bindKey(["ctrl+2", "meta+2"], () => {
        const zoom = graph.zoom()
        if (zoom > 0.5) {
            graph.zoom(-0.1)
        }
    })

    // 控制连接桩显示/隐藏
    const showPorts = (ports: NodeListOf<SVGElement>, show: boolean) => {
        for (let i = 0, len = ports.length; i < len; i = i + 1) {
            ports[i].style.visibility = show ? "visible" : "hidden"
        }
    }
    graph.on("node:mouseenter", () => {
        const container = document.getElementById("graph-container")!
        const ports = container.querySelectorAll(".x6-port-body") as NodeListOf<SVGElement>
        showPorts(ports, true)
    })
    graph.on("node:mouseleave", () => {
        const container = document.getElementById("graph-container")!
        const ports = container.querySelectorAll(".x6-port-body") as NodeListOf<SVGElement>
        showPorts(ports, false)
    })
    // #endregion

    // #region 初始化图形
    const ports = {
        groups: {
            top: {
                position: "top",
                attrs: {
                    circle: {
                        r: 4,
                        magnet: true,
                        stroke: "#5F95FF",
                        strokeWidth: 1,
                        fill: "#fff",
                        style: {
                            visibility: "hidden",
                        },
                    },
                },
            },
            right: {
                position: "right",
                attrs: {
                    circle: {
                        r: 4,
                        magnet: true,
                        stroke: "#5F95FF",
                        strokeWidth: 1,
                        fill: "#fff",
                        style: {
                            visibility: "hidden",
                        },
                    },
                },
            },
            bottom: {
                position: "bottom",
                attrs: {
                    circle: {
                        r: 4,
                        magnet: true,
                        stroke: "#5F95FF",
                        strokeWidth: 1,
                        fill: "#fff",
                        style: {
                            visibility: "hidden",
                        },
                    },
                },
            },
            left: {
                position: "left",
                attrs: {
                    circle: {
                        r: 4,
                        magnet: true,
                        stroke: "#5F95FF",
                        strokeWidth: 1,
                        fill: "#fff",
                        style: {
                            visibility: "hidden",
                        },
                    },
                },
            },
        },
        items: [
            {
                group: "top",
            },
            {
                group: "right",
            },
            {
                group: "bottom",
            },
            {
                group: "left",
            },
        ],
    }

    Graph.registerNode(
        "custom-rect",
        {
            inherit: "rect",
            width: 66,
            height: 36,
            attrs: {
                body: {
                    strokeWidth: 1,
                    stroke: "#5F95FF",
                    fill: "#EFF4FF",
                },
                text: {
                    fontSize: 12,
                    fill: "#262626",
                },
            },
            ports: { ...ports },
        },
        true
    )

    Graph.registerNode(
        "custom-polygon",
        {
            inherit: "polygon",
            width: 66,
            height: 36,
            attrs: {
                body: {
                    strokeWidth: 1,
                    stroke: "#5F95FF",
                    fill: "#EFF4FF",
                },
                text: {
                    fontSize: 12,
                    fill: "#262626",
                },
            },
            ports: {
                ...ports,
                items: [
                    {
                        group: "top",
                    },
                    {
                        group: "bottom",
                    },
                ],
            },
        },
        true
    )

    Graph.registerNode(
        "custom-circle",
        {
            inherit: "circle",
            width: 45,
            height: 45,
            attrs: {
                body: {
                    strokeWidth: 1,
                    stroke: "#5F95FF",
                    fill: "#EFF4FF",
                },
                text: {
                    fontSize: 12,
                    fill: "#262626",
                },
            },
            ports: { ...ports },
        },
        true
    )

    Graph.registerNode(
        "custom-image",
        {
            inherit: "rect",
            width: 52,
            height: 52,
            markup: [
                {
                    tagName: "rect",
                    selector: "body",
                },
                {
                    tagName: "image",
                },
                {
                    tagName: "text",
                    selector: "label",
                },
            ],
            attrs: {
                body: {
                    stroke: "#5F95FF",
                    fill: "#5F95FF",
                },
                image: {
                    width: 26,
                    height: 26,
                    refX: 13,
                    refY: 16,
                },
                label: {
                    refX: 3,
                    refY: 2,
                    textAnchor: "left",
                    textVerticalAnchor: "top",
                    fontSize: 12,
                    fill: "#fff",
                },
            },
            ports: { ...ports },
        },
        true
    )

    // const r1 = graph.createNode({
    //     shape: "custom-rect",
    //     label: "开始",
    //     attrs: {
    //         body: {
    //             rx: 20,
    //             ry: 26,
    //         },
    //     },
    // })
    // const r2 = graph.createNode({
    //     shape: "custom-rect",
    //     label: "过程",
    // })
    // const r3 = graph.createNode({
    //     shape: "custom-rect",
    //     attrs: {
    //         body: {
    //             rx: 6,
    //             ry: 6,
    //         },
    //     },
    //     label: "可选过程",
    // })
    // const r4 = graph.createNode({
    //     shape: "custom-polygon",
    //     attrs: {
    //         body: {
    //             refPoints: "0,10 10,0 20,10 10,20",
    //         },
    //     },
    //     label: "决策",
    // })
    // const r5 = graph.createNode({
    //     shape: "custom-polygon",
    //     attrs: {
    //         body: {
    //             refPoints: "10,0 40,0 30,20 0,20",
    //         },
    //     },
    //     label: "数据",
    // })
    // const r6 = graph.createNode({
    //     shape: "custom-circle",
    //     label: "连接",
    // })
    const r1 = graph.createNode({
        // shape: "cylinder",
        width: 60,
        height: 60,
        zIndex: 1,
        label: "LDC",
        attrs: {
            label: {
                refX: 10,
                refY: 10,
                fontSize: 14,
                textAnchor: "start",
                textVerticalAnchor: "top",
            },
            body: {
                fill: "#fffbe6",
                stroke: "#ffe7ba",
            },
        },
    })
    stencil.load([r1], "group1")

    const r2 = graph.createNode({
        shape: "custom-polygon",
        attrs: {
            body: {
                refPoints: "10,0 40,0 30,20 0,20",
            },
        },
        label: "网关",
        // ports: { ...ports },
    })

    const r3 = graph.createNode({
        shape: "cylinder",
        width: 60,
        height: 50,
        label: "数据库",
        attrs: {
            top: {
                fill: "#fe854f",
                fillOpacity: 0.5,
            },
            body: {
                fill: "#ED8A19",
                fillOpacity: 0.8,
            },
        },
        ports: { ...ports },
    })
    stencil.load([r2, r3], "group2")


    const r4 = graph.createNode({
        width: 60,
        height: 60,
        label: "业务域",
        zIndex: 13,
        attrs: {
            body: {
                stroke: "none",
                fill: "#47C769",
            },
            label: {
                refX: 10,
                refY: 10,
                fill: "#fff",
                fontSize: 14,
                textAnchor: "start",
                textVerticalAnchor: "top",
            },
        },
    })

    const r5 = graph.createNode({
        label: "业务模块",
        shape: "custom-rect",
        attrs: {
            body: {
                rx: 6,
                ry: 6,
            },
        },
    })
    stencil.load([r4, r5], "group3")
    
    const q1 = graph.createNode({
        // shape: "cylinder",
        width: 60,
        height: 60,
        zIndex: 1,
        label: "张江",
        attrs: {
            label: {
                refX: 10,
                refY: 10,
                fontSize: 14,
                textAnchor: "start",
                textVerticalAnchor: "top",
            },
            body: {
                fill: "#fffbe6",
                stroke: "#ffe7ba",
            },
        },
    })
    stencil.load([q1], "group4")

    const imageShapes = [
        {
            label: "注册中心",
            image: "https://gw.alipayobjects.com/zos/bmw-prod/687b6cb9-4b97-42a6-96d0-34b3099133ac.svg",
        },
        // {
        //     label: "Http",
        //     image: "https://gw.alipayobjects.com/zos/bmw-prod/dc1ced06-417d-466f-927b-b4a4d3265791.svg",
        // },
        // {
        //     label: "Api",
        //     image: "https://gw.alipayobjects.com/zos/bmw-prod/c55d7ae1-8d20-4585-bd8f-ca23653a4489.svg",
        // },
        // {
        //     label: "Sql",
        //     image: "https://gw.alipayobjects.com/zos/bmw-prod/6eb71764-18ed-4149-b868-53ad1542c405.svg",
        // },
        // {
        //     label: "Clound",
        //     image: "https://gw.alipayobjects.com/zos/bmw-prod/c36fe7cb-dc24-4854-aeb5-88d8dc36d52e.svg",
        // },
        // {
        //     label: "Mq",
        //     image: "https://gw.alipayobjects.com/zos/bmw-prod/2010ac9f-40e7-49d4-8c4a-4fcf2f83033b.svg",
        // },
    ]
    const imageNodes = imageShapes.map((item) =>
        graph.createNode({
            shape: "custom-image",
            label: item.label,
            attrs: {
                image: {
                    "xlink:href": item.image,
                },
            },
        })
    )
    stencil.load(imageNodes, "group4")
    // #endregion

    // 渲染图形
    // graph.fromJSON(data)
})
function preWork() {
    const container = document.getElementById("container")!
    const stencilContainer: any = document.getElementById("stencil")
    container.appendChild(stencilContainer)
    const graphContainer: any = document.getElementById("graph-container")
    container.appendChild(graphContainer)
}
</script>
<template>
    <div id="container">
        <div id="graph-container" />
        <a-tabs v-model:activeKey="activeKey" type="card">
            <a-tab-pane key="1" tab="视图">
                <div class="tab-views">
                    <div class="views-dl">
                        <div class="views-msg"></div>
                        <p class="views-title">账户核心系统 - 部署视图</p>
                    </div>
                    <div class="views-dl">
                        <div class="views-msg"></div>
                        <p class="views-title">账户核心系统 - 实例视图</p>
                    </div>
                    <div class="views-dl">
                        <div class="views-msg"></div>
                        <p class="views-title">账户核心系统 - 服务视图</p>
                    </div>
                    <a-button>添加</a-button>
                </div>
            </a-tab-pane>
            <a-tab-pane key="2" tab="组件">
                <div v-show="activeKey == '2'" id="stencil" class="tab-stencil" />
            </a-tab-pane>
        </a-tabs>
        <Right class="right" />
    </div>
</template>
<style scoped>
#container {
    display: flex;
    /* width: 100%; */
    width: calc(100% - 300px);
    height: 600px;
    border: 1px solid #dfe3e8;
}
#stencil {
    width: 200px;
    height: 100%;
    position: relative;
    border-right: 1px solid #dfe3e8;
}
#graph-container {
    width: calc(100% - 200px) !important;
    height: 100% !important;
}
.x6-widget-stencil {
    background-color: #fff;
}
.x6-widget-stencil-title {
    background-color: #fff;
}
.x6-widget-stencil-group-title {
    background-color: #fff !important;
}
:deep(.x6-widget-stencil-content::-webkit-scrollbar) {
    width: 4px;
    overflow-y: scroll;
}
:deep(.x6-widget-stencil-content::-webkit-scrollbar-thumb) {
    border-radius: 6px;
    background: rgb(156, 156, 156);
}
:deep(.x6-widget-stencil-content::-webkit-scrollbar-track) {
    background: #cccbcb;
}
.x6-widget-transform {
    margin: -1px 0 0 -1px;
    padding: 0px;
    border: 1px solid #239edd;
}
.x6-widget-transform > div {
    border: 1px solid #239edd;
}
.x6-widget-transform > div:hover {
    background-color: #3dafe4;
}
.x6-widget-transform-active-handle {
    background-color: #3dafe4;
}
.x6-widget-transform-resize {
    border-radius: 0;
}
.x6-widget-selection-inner {
    border: 1px solid #239edd;
}
.x6-widget-selection-box {
    opacity: 0;
}
.tab-stencil {
    margin-left: -176px;
    margin-top: 40px;
}
.tab-views {
    display: flex;
    flex-wrap: wrap;
    /* align-items: center; */
    justify-content: center;
    padding: 20px 0;
    width: 200px;
    height: 600px;
    background-color: #f5f5f5;
}
.views-dl {
    display: flex;
    flex-wrap: wrap;
    /* align-items: center; */
    justify-content: center;
}
.views-msg {
    /* margin: 0 20px; */
    /* width: 140px; */
    width: 140px;
    height: 80px;
    border-radius: 5px;
    background-color: #ccc;
}
.views-title {
    text-align: center;
    font-size: 16;
    font-weight: 500;
}
</style>
